#include "./Presentation.h"
#include "../Core/PlayerArray.h"

#include <iostream>

using namespace Graphics;

void Presentation::render( long dt ) {

	Core::Player* player = Core::PlayerArray::getInstance().getLocalPlayer();
	GameLogic::Objects::GameObject *obj = player->controlled_object;

	if( obj != 0) {
		Vec2f v = obj->getPosition();

		float modifier = 0.0f;

		if( player->team == TEAM_NINJAS )
			modifier = -1.0f;
		else
			modifier = 1.0f;

		main_cam_->setPosition(
			toOgreCoords( v.x ),
			150.0f,
			toOgreCoords( v.y ) - 1.0f
		);

		main_cam_->lookAt(
			toOgreCoords( v.x ),
			0.0f,
			toOgreCoords( v.y )
		);

	}

	root_->renderOneFrame();
}

using namespace Ogre;

Ogre::SceneNode* Presentation::createSceneNode( Ogre::Entity* entity ) {
	Ogre::SceneNode* scene_node = scene_manager_->createSceneNode();
	scene_manager_->getRootSceneNode()->addChild( scene_node );
	scene_node->attachObject( entity );
	return scene_node;
}

Ogre::SceneNode* Presentation::createSceneNode( Ogre::Entity* entity, Ogre::SceneNode* parent ) {
	Ogre::SceneNode* scene_node = scene_manager_->createSceneNode();
	parent->addChild( scene_node );
	scene_node->attachObject( entity );
	return scene_node;
}


void Presentation::createSphere(const std::string& strName, const float r, const int nRings, const int nSegments, const std::string& useMaterial)
{
    ManualObject * manual = Graphics::Presentation::getInstance().getSceneManager()->createManualObject(strName+"e");
    manual->begin(useMaterial, RenderOperation::OT_TRIANGLE_LIST);

    float fDeltaRingAngle = (Math::PI / nRings);
    float fDeltaSegAngle = (2 * Math::PI / nSegments);
    unsigned short wVerticeIndex = 0 ;

    // Generate the group of rings for the sphere
    for( int ring = 0; ring <= nRings; ring++ ) {
        float r0 = r * sinf (ring * fDeltaRingAngle);
        float y0 = r * cosf (ring * fDeltaRingAngle);

        // Generate the group of segments for the current ring
        for(int seg = 0; seg <= nSegments; seg++) {
            float x0 = r0 * sinf(seg * fDeltaSegAngle);
            float z0 = r0 * cosf(seg * fDeltaSegAngle);

            // Add one vertex to the strip which makes up the sphere
            manual->position( x0, y0, z0);
            manual->normal(Vector3(x0, y0, z0).normalisedCopy());
            manual->textureCoord((float) seg / (float) nSegments, (float) ring / (float) nRings);

            if (ring != nRings) {
                // each vertex (except the last) has six indicies pointing to it
                manual->index(wVerticeIndex + nSegments + 1);
                manual->index(wVerticeIndex);
                manual->index(wVerticeIndex + nSegments);
                manual->index(wVerticeIndex + nSegments + 1);
                manual->index(wVerticeIndex + 1);
                manual->index(wVerticeIndex);
                wVerticeIndex ++;
                }
        }; // end for seg
    } // end for ring
    manual->end();
    MeshPtr mesh = manual->convertToMesh(strName);
    mesh->_setBounds( AxisAlignedBox( Vector3(-r, -r, -r), Vector3(r, r, r) ), true );

    mesh->_setBoundingSphereRadius(r);
       unsigned short src, dest;
       if (!mesh->suggestTangentVectorBuildParams(VES_TANGENT, src, dest))
       {
                 mesh->buildTangentVectors(VES_TANGENT, src, dest);
       }
} //createSphere()

Presentation::Presentation():
	root_( 0 ),
	main_cam_( 0 ),
	scene_manager_( 0 ),
	render_window_( 0 )
{

}

Presentation::~Presentation() {

}

void Presentation::windowResized(Ogre::RenderWindow* rw) {

}

void Presentation::windowClosed(Ogre::RenderWindow* rw) {

}

bool Presentation::init() {

    root_ = new Ogre::Root( "./plugins.cfg", "./ogre.cfg", Ogre::StringUtil::BLANK );

////////////

    Ogre::ConfigFile config_file;
    std::cout << "== res loading starts NOW ==" << std::endl;
    config_file.load( "resources.cfg" );

    Ogre::ConfigFile::SectionIterator iter = config_file.getSectionIterator();

    Ogre::String sec="lolz", type, arch;

    while( iter.hasMoreElements() ) {
    	std::string name = iter.peekNextKey();
    	Ogre::ConfigFile::SettingsMultiMap *settings = iter.getNext();
    	Ogre::ConfigFile::SettingsMultiMap::iterator settings_iter;
    	for( settings_iter = settings->begin(); settings_iter != settings->end(); ++settings_iter ) {
    		type = settings_iter->first;
    		arch = settings_iter->second;
    		Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
    			arch, type, sec
    		); //folder, typ, grupa
    	}
    }

    std::cout << "== restoring config NOW ==" << std::endl;

    if( root_->restoreConfig() || root_->showConfigDialog() ) {
    	render_window_ = root_->initialise( true, "PvPC" );
    } else {
    	return false;
    }

    std::cout << "== creating scene manager ==" << std::endl;

    scene_manager_ = root_->createSceneManager( Ogre::ST_GENERIC );

    std::cout << "== creating camera ==" << std::endl;

    main_cam_ = scene_manager_->createCamera("MainCam");
    main_cam_->setPosition(260.0f,200.0f,300.0f);
    main_cam_->lookAt(260.0f,200.0f,0.0f);

    //tworzy viewport:
    Ogre::Viewport* vp = render_window_->addViewport( main_cam_ );
    vp->setBackgroundColour( Ogre::ColourValue(0.5f,0.5f,0.5f) );

    main_cam_->setAspectRatio(
    		Ogre::Real(vp->getActualWidth()) / Ogre::Real(vp->getActualHeight())
    );
    main_cam_->setNearClipDistance(5.0f);

    Ogre::TextureManager::getSingleton().setDefaultNumMipmaps( 5 );

    //grupy zasobow?
    Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();

    //windowResized( render_window_ );

    //rejestruje sie jako sluchacz zdarzen okna, aby przechwytywac jego zdarzenia
    Ogre::WindowEventUtilities::addWindowEventListener( render_window_, this );

    /////

    createSphere("meshActor", 1.0f, 8, 8);

    std::cout << "== Presentation created. ==" << std::endl;

    return true;
}
